package org.example.config;

import lombok.Getter;
import lombok.Setter;
import org.example.binding.MapperRegistry;
import org.example.datasource.Environment;
import org.example.executor.Executor;
import org.example.executor.SimpleExecutor;
import org.example.executor.parameter.DefaultParameterHandler;
import org.example.executor.parameter.ParameterHandler;
import org.example.executor.result.DefaultResultSetHandler;
import org.example.executor.result.ResultSetHandler;
import org.example.executor.statement.RoutingStatementHandler;
import org.example.executor.statement.StatementHandler;
import org.example.mapping.BoundSql;
import org.example.mapping.MappedStatement;
import org.example.reflection.DefaultObjectFactory;
import org.example.reflection.DefaultReflectorFactory;
import org.example.reflection.ObjectFactory;
import org.example.reflection.ReflectorFactory;
import org.example.session.DefaultSqlSession;
import org.example.session.ResultHandler;
import org.example.session.RowBounds;
import org.example.type.TypeAliasRegistry;
import org.example.type.TypeHandler;
import org.example.type.TypeHandlerRegistry;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Getter
@Setter
public class Configuration {
    //别名注册器
    protected final TypeAliasRegistry typeAliasRegistry = new TypeAliasRegistry();
    //类型注册器
    protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
    //mapper注册器
    protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
    //对象创建工厂
    protected ObjectFactory objectFactory = new DefaultObjectFactory();
    protected ReflectorFactory reflectorFactory = new DefaultReflectorFactory();
    //存储SQL
    protected final Map<String, MappedStatement> mappedStatements = new ConcurrentHashMap<>();
    //环境对象
    private Environment enironment;
    public TypeAliasRegistry getTypeAliasRegistry() {
        return typeAliasRegistry;
    }

    public void setEnvironment(Environment enironment) {
        this.enironment = enironment;
    }

    public void setMappedStatement(MappedStatement mappedStatement) {
        this.mappedStatements.put(mappedStatement.getId(),mappedStatement);
    }

    public Executor newSimpleExecutor() {
        return new SimpleExecutor(this);
    }

    public <T> T getMapper(Class<T> type, DefaultSqlSession defaultSqlSession) {
        return mapperRegistry.getMapper(type, defaultSqlSession);
    }
    public <T> void addMapper(Class<T> type) {
        mapperRegistry.addMapper(type);
    }

    public MappedStatement getMappedStatements(Class<?> mapperInterface, String methodName) {
        String statementId = mapperInterface.getName() + "." + methodName;
        return mappedStatements.get(statementId);
    }

    public StatementHandler newStatementHandler(Executor wrapper, MappedStatement ms, Object parameter, RowBounds rowBounds,ResultHandler resultHandler, BoundSql boundSql) {
        StatementHandler statementHandler = new RoutingStatementHandler(wrapper, ms, parameter, rowBounds, resultHandler, boundSql);
        //TODO 添加拦截器
        return statementHandler;
    }

    public ParameterHandler newParameterHandler(MappedStatement mappedStatement, Object parameterObject, BoundSql boundSql) {
        return new DefaultParameterHandler(mappedStatement, parameterObject, boundSql);
    }

    public TypeHandler<?> getTypeHandler(Class<?> cls) {
        return typeHandlerRegistry.getAllTypeHandlersMap().get(cls);
    }

    public ResultSetHandler newResultSetHandler(Executor wrapper, MappedStatement ms, RowBounds rowBounds, ParameterHandler parameterHandler, ResultHandler resultHandler, BoundSql boundSql) {
        return new DefaultResultSetHandler( wrapper,  ms,  parameterHandler, resultHandler,  boundSql, rowBounds);
    }

    public ReflectorFactory getReflectorFactory() {
        return this.reflectorFactory;
    }

//    protected final MapperRegistry mapperRegistry = new MapperRegistry(this);
//    protected final TypeHandlerRegistry typeHandlerRegistry = new TypeHandlerRegistry();
//    protected final Map<String, ResultMap> resultMaps = new StrictMap<>("Result Maps collection");
//    protected final Map<String, ParameterMap> parameterMaps = new StrictMap<>("Parameter Maps collection");
//
//    public void addMappers(String packageName, Class<?> superType) {
//        mapperRegistry.addMappers(packageName, superType);
//    }
}
